// 2、无头双向链表实现
 public class LinkedList {
    static class Listnode {
        public int val;
        public Listnode prev;
        public Listnode next;

        public Listnode(int val) {
            this.val = val;
        }
    }

    public Listnode head;
    public Listnode tail;

    //头插法
    public void addFirst(int data) {
        Listnode node = new Listnode(data);
        if (this.head == null) {
            this.head = node;
            this.tail = node;
        } else {
            node.next = this.head;
            this.head.prev = node;
            head = node;

        }
    }

    //尾插法
    public void addLast(int data) {
        Listnode node = new Listnode(data);
        if (head == null) {
            this.head = node;
            this.tail = node;
        }
        this.tail.next = node;
        node.prev = this.tail;
        this.tail = node;
    }
    //任意位置插入,第一个数据节点为0号下标
    public void addIndex(int index, int data)
            throws IndexWrongException {
        if (index < 0 || index > size()) {
            throw new IndexWrongException("插入的位置错误");
        }
        if (index == 0) {
            addFirst(data);
            return;
        }
        if (index == size()) {
            addLast(data);
            return;
        }
        Listnode flag = FindIndex(index);
        Listnode node = new Listnode(data);
        flag.prev.next = node;
        node.next = flag;
        node.prev = flag.prev;
        flag.prev = node;
    }

    protected Listnode FindIndex(int index) {
        Listnode cur = this.head;
        while (index != 0) {
            cur = cur.next;
            index--;
        }
       return  cur;
    }
     //查找是否包含关键字key是否在单链表当中
     public boolean contains(int key){
         Listnode cur=this.head;
         while(cur!=null){
             if(cur.val==key){
                 return  true;
             }
             cur=cur.next;
         }
         return false;
     }
     //删除第一次出现关键字为key的节点
     public void remove(int key){
        if(size()==0){
            return ;
        }
        if(this.head.val==key){
            this.head=this.head.next;
            return;
        }
        if(this.tail.val==key){
            this.tail.prev.next=null;
            return ;
        }
       Listnode flag=FindKey(key);
            if(flag==null){
                System.out.println("查无此数，无法删除");
            }
            flag.prev.next=flag.next;
            flag.next.prev=flag.prev;
         }

     protected Listnode FindKey(int key){
        if(this.head==null){
            return null;
        }
        Listnode cur=this.head;
        while(cur!=null){
            if(cur.val==key){
                return cur;
            }
            cur=cur.next;
        }
        return null;
     }

     //删除所有值为key的节点
     public void removeAllKey(int key) {
         Listnode cur = head;
         while (cur != null) {
             if(cur.val == key) {
                 if(cur == head) {
                     head = head.next;//头删
                     if(head != null) {//判断是否只有一个节点
                         head.prev = null;
                     }else {
                         tail = null;
                     }
                 }else {
                     cur.prev.next = cur.next;
                     if(cur.next != null) {
                         cur.next.prev = cur.prev;
                     }else {
                         this.tail = cur.prev;//尾删
                     }
                 }
             }
             cur = cur.next;
         }
     }
    //得到单链表的长度
     public int size(){
         Listnode cur=this.head;
         int count=0;
         while(cur!=null){
             count++;
             cur=cur.next;
         }
         return count;
     }

     public void display(){
         Listnode cur=this.head;
         while(cur!=null){
             System.out.print(cur.val+" ");
             cur=cur.next;
         }
         System.out.println();
     }
     public void clear(){
        Listnode cur=this.head;
        while(cur!=null){
            Listnode curNext=cur.next;
            cur.prev=null;
            cur.next=null;
            cur=curNext;
        }
        this.tail=null;
        this.head=null;
     }

 }